import random
from django import forms
from web import models
from django.core.validators import RegexValidator
from django.core.exceptions import ValidationError
from django.conf import settings
from django_redis import get_redis_connection
from django.conf import settings
from untils.aliyun.sms import send_sms
from untils import encrypt
from web.forms.bootstrap import BootStrapForm


class RegisterModelForm(BootStrapForm, forms.ModelForm):
    mobile_phone = forms.CharField(label="手机号", validators=[RegexValidator(r'^1[3|4|5|6|7|8|9]\d{9}$', '手机号格式错误')])
    password = forms.CharField(label="密码", widget=forms.PasswordInput(),
                               min_length=8, max_length=64,
                               error_messages={'min_length': '密码长度不能少于8个字符', 'max_length': '密码长度不能大64个字符'})
    confirm_password = forms.CharField(label="重复密码", widget=forms.PasswordInput(),
                                       min_length=8, max_length=64,
                                       error_messages={'min_length': '重复密码长度不能少于8个字符', 'max_length': '重复密码长度不能大64个字符'})
    code = forms.CharField(label="验证码")

    class Meta:
        model = models.UserInfo
        fields = ['username', 'email', 'password', 'confirm_password', 'mobile_phone', 'code']

    def clean_username(self):
        username = self.cleaned_data['username']

        exists = models.UserInfo.objects.filter(username=username).exists()

        if exists:
            raise ValidationError("用户名已存在")

        return username

    def clean_email(self):
        email = self.cleaned_data['email']

        exists = models.UserInfo.objects.filter(email=email).exists()

        if exists:
            raise ValidationError("邮箱已存在")

        return email

    def clean_password(self):
        password = self.cleaned_data['password']

        return encrypt.md5(password)

    def clean_confirm_password(self):
        password = self.cleaned_data['password']
        confirm_password = encrypt.md5(self.cleaned_data['confirm_password'])

        if confirm_password != password:
            raise ValidationError("两次密码输入不一致")
        return confirm_password

    def clean_mobile_phone(self):
        mobile_phone = self.cleaned_data['mobile_phone']

        exists = models.UserInfo.objects.filter(mobile_phone=mobile_phone).exists()

        if exists:
            raise ValidationError("手机号已注册")

        return mobile_phone

    def clean_code(self):
        mobile_phone = self.cleaned_data.get('mobile_phone')
        code = self.cleaned_data['code']

        if not mobile_phone:
            return code

        conn = get_redis_connection()
        redis_code = conn.get(mobile_phone)

        if not redis_code:
            raise ValidationError("验证码失效或未发送，请重新发送")

        str_redis_code = redis_code.decode('utf-8')

        if code.strip() != str_redis_code:
            raise ValidationError("验证码错误，请重新输入")

        return code


class SendSmsForm(forms.Form):
    mobile_phone = forms.CharField(label="手机号", validators=[RegexValidator(r'^1[3|4|5|6|7|8|9]\d{9}$', '手机号格式错误')])

    def __init__(self, request, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.request = request

    def clean_mobile_phone(self):

        mobile_phone = self.cleaned_data['mobile_phone']

        tpl = self.request.GET.get('tpl')

        template_id = settings.TEMPLATE_CODE.get(tpl)

        if not template_id:
            raise ValidationError("短信模板错误")

        exists = models.UserInfo.objects.filter(mobile_phone=mobile_phone).exists()

        if tpl == 'register':
            if exists:
                raise ValidationError("该手机号已存在")
        elif tpl == 'login':
            if not exists:
                raise ValidationError("该手机号未注册")

        # 短信验证

        code = random.randrange(1000, 9999)
        code_str = {'code': code}
        sms = send_sms(mobile_phone, template_id, str(code_str))
        if sms['Message'] != "OK":
            raise ValidationError("短信发送失败")

        #
        conn = get_redis_connection("default")
        conn.set(mobile_phone, code, ex=60)

        return mobile_phone


class LoginSmsForm(BootStrapForm, forms.Form):
    mobile_phone = forms.CharField(label="手机号", validators=[RegexValidator(r'^1[3|4|5|6|7|8|9]\d{9}$', '手机号格式错误')])
    code = forms.CharField(label="验证码")

    def clean_mobile_phone(self):
        mobile_phone = self.cleaned_data['mobile_phone']

        exists = models.UserInfo.objects.filter(mobile_phone=mobile_phone).exists()

        if exists == False:
            raise ValidationError("该手机号还未注册")
        return mobile_phone

    def clean_code(self):
        mobile_phone = self.cleaned_data.get('mobile_phone')
        code = self.cleaned_data['code']

        if not mobile_phone:
            return code

        conn = get_redis_connection()
        redis_code = conn.get(mobile_phone)

        if not redis_code:
            raise ValidationError("验证码失效或未发送，请重新发送")

        str_redis_code = redis_code.decode('utf-8')

        if code != str_redis_code:
            raise ValidationError('验证码错误，请重新输入')

        return code


class LoginForm(BootStrapForm, forms.Form):
    username = forms.CharField(label="手机号或邮箱", )
    password = forms.CharField(label="密码", widget=forms.PasswordInput(render_value=True))
    code = forms.CharField(label='验证码')

    def __init__(self, request, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.request = request

    def clean_password(self):
        password = self.cleaned_data['password']

        return encrypt.md5(password)

    def clean_code(self):
        code = self.cleaned_data['code']
        image_code = self.request.session.get('code')

        if not image_code:
            raise ValidationError("验证码已失效或未发送")

        if code.strip().upper() != image_code.strip().upper():
            raise ValidationError("验证码错误,请重新输入")

        return code
